iT邦幫忙

2026 iThome 鐵人賽

DAY 19
1
Build on Google AI

從 Vibe Coding 到 Production:用 Google AI 打造上線守門員系列 第 19

Day 19|設計檢查規則:把資安、隱私與 SRE 知識交給 Agent

  • 分享至 

  • xImage
  •  

Day 18,我們建立了 architecture.json

Agent 現在知道 Demo 是一個 Firebase Web App,也知道 Browser 會直接存取 Firestore。

下一個問題是:Agent 應該檢查什麼?

最直覺的方法,是把一大段 Checklist 放進 Prompt:

請檢查:
- 是否有 Broken Access Control
- 是否洩漏個資
- 是否缺少 Timeout
- 是否缺少 Health Check
- 是否暴露 API Key

這種 Prompt 看起來涵蓋很多問題,實際執行時卻會產生三種噪音:

  1. 對純前端網站要求 Server Health Check。
  2. 看到 Firebase Web API Key 就回報 Secret 洩漏。
  3. 看到外部 API 呼叫沒有 Timeout,就直接宣告正式環境會故障。

今天要把前 7 至 15 天累積的資安、隱私與 SRE 知識,轉成 Agent 可以選擇、執行與追蹤版本的規則。

每條規則不只描述「最佳實務」,還要定義:

  • 什麼架構才適用。
  • 需要哪些證據。
  • 如何判斷。
  • 證據不足時應輸出什麼。
  • 下一步如何驗證。

Checklist 與規則有什麼不同?

Checklist 通常是一個問題:

系統是否有適當的存取控制?

這句話適合提醒人類,卻不足以驅動 Agent。

Agent 還需要知道:

「適當」是什麼?
哪些元件適用?
要讀哪些證據?
看到什麼才算失敗?
靜態證據能否直接確認漏洞?

因此,Vibe Guard 的規則至少包含以下欄位:

{
  "id": "SEC-AUTHZ-001",
  "version": "1.0.0",
  "domain": "security",
  "title": "User-owned records enforce ownership on every operation",
  "source": "OWASP ASVS access control",
  "appliesWhen": "browser_direct_firestore",
  "requiredEvidence": [
    "firestore.rules",
    "project ownership field",
    "read and write query path"
  ],
  "evaluator": "firestore_owner_check",
  "failureVerdict": "candidate"
}

title 說明期待的安全狀態。

appliesWhen 決定這條規則是否適合目前架構。

requiredEvidence 告訴 Agent,做出判斷前要收集哪些資料。

evaluator 對應實際檢查邏輯。

failureVerdict 則限制規則失敗時可以使用的最高結論。

這裡刻意設定為 candidate,而不是 confirmed

只看到過寬的 Firestore Rules,可以建立越權假設;要成為 Confirmed Finding,仍要通過 Day 17 的攻擊路徑、邊界跨越、重現與影響門檻。

規則需要穩定 ID 與版本

如果規則只有自然語言名稱:

檢查存取控制

幾個月後修改內容,很難回答:

  • 哪個版本產生這份 Finding?
  • 規則何時改變嚴重度?
  • 舊報告是否需要重新執行?
  • 誤報是模型問題,還是規則定義問題?

因此每條規則使用不隨標題改變的 ID:

SEC-AUTHZ-001
PRIV-MIN-001
REL-TIMEOUT-001
SEC-SECRET-001
SRE-HEALTH-001

Domain 前綴讓結果可以依資安、隱私與可靠性分流。

版本則採用:

1.0.0

如果只修正文案,可以增加 Patch。

如果新增證據欄位或改變判斷結果,可以增加 Minor。

如果規則語意已不相容,就增加 Major。

報告未來應同時保存:

{
  "ruleId": "SEC-AUTHZ-001",
  "ruleVersion": "1.0.0"
}

這樣評估資料集才能重播相同條件。

先判斷適不適用,再尋找問題

Day 18 的 Recon 已經輸出:

{
  "from": "Browser",
  "to": "Cloud Firestore emulator",
  "data": "Project records and authenticated identity"
}

Rule Engine 可以使用這項架構事實判斷:

case "browser_direct_firestore":
  return boundaries.some(
    (boundary) =>
      boundary.from === "Browser" &&
      boundary.to.includes("Cloud Firestore")
  );

只有 Browser 直接存取 Firestore 時,SEC-AUTHZ-001 才進入評估。

另一條規則要求長駐 Server 提供 Liveness 與 Readiness:

{
  "id": "SRE-HEALTH-001",
  "appliesWhen": "long_running_server",
  "evaluator": "health_endpoints"
}

目前 Demo 的架構類型是:

Local-only Firebase web application

它沒有 Repository 內的長駐 Application Server。

所以結果應該是:

SRE-HEALTH-001 NOT_APPLICABLE

而不是:

Critical: Application has no /health endpoint.

Not Applicable 不是忽略風險,而是證明 Agent 有先理解架構。

不同知識需要不同證據

今天加入五條示範規則:

Rule Domain 需要回答的問題
SEC-AUTHZ-001 Security 使用者擁有的資料是否在每個操作檢查 Owner?
PRIV-MIN-001 Privacy 儲存與顯示的個資是否為功能必要?
REL-TIMEOUT-001 Reliability 外部呼叫是否有明確 Deadline?
SEC-SECRET-001 Security Client 中的 Key 是否具備特權?
SRE-HEALTH-001 Reliability 長駐 Server 是否有健康檢查?

這五條規則不能共用同一種證據。

授權規則需要:

Security Rules
資料所有權欄位
實際讀寫路徑
兩個帳號的動態測試

個資最小化需要:

收集與保存的欄位
誰能讀取
畫面是否顯示
產品需求與保存目的

Timeout 規則需要:

外部呼叫位置
SDK 預設行為
Application Deadline
Retry 與上游 Timeout

如果沒有產品需求,Agent 可以指出 ownerEmail 被保存及顯示,卻不能自行斷言這個欄位一定沒有合法用途。

因此它先輸出 Candidate,並要求補充功能需求與可讀取範圍。

不要把所有 API Key 都當成 Secret

Demo 的 Firebase Client Configuration 包含:

apiKey: "demo-api-key"

只做字串掃描的工具可能立即回報:

High: API Key committed to source code.

但這個值用於本機 Firebase Emulator,而且程式會拒絕在非 Localhost 執行。

它不是 GEMINI_API_KEY,也沒有證據顯示能呼叫具特權的正式環境服務。

規則的判斷邏輯會同時檢查用途與執行環境:

const localOnly = mainSource.includes(
  "This intentionally vulnerable demo can only run locally."
);
const emulatorKey = mainSource.includes('apiKey: "demo-api-key"');

return localOnly && emulatorKey
  ? {
      verdict: "pass",
      evidence:
        "The value identifies a localhost-only Firebase Emulator project and is not a Gemini credential."
    }
  : {
      verdict: "requires_evidence",
      nextStep: "Inspect enabled APIs and key restrictions."
    };

這裡的重點不是用字串比對證明所有 Key 都安全。

重點是規則不能只因變數名稱包含 apiKey,就跳過金鑰用途、權限與限制條件。

沒有看到 Timeout,不代表已確認故障

Reviewer 會呼叫 Gemini:

ai.interactions.create(...)

目前 Application Code 沒有設定明確 Deadline。

Rule Engine 可以確認:

The Gemini call site has no explicit deadline in application code.

但它還不知道:

  • SDK 是否有預設 Timeout。
  • 底層 Transport 是否限制等待時間。
  • CLI 的可接受執行時間是多少。
  • 外層 Process 是否另有 Deadline。

所以這條規則輸出:

REL-TIMEOUT-001 REQUIRES_EVIDENCE

並要求:

Check SDK defaults and define the end-to-end review deadline.

這個分類可以避免把「缺少可見設定」直接寫成「服務會永遠卡住」。

Google SRE 的 Production Service Practices 建議每個 RPC Client 使用帶 Jitter 的 Exponential Backoff,也強調服務應在過載時合理降級。

不過,SRE 原則仍要轉成符合系統邊界的測試,不能只把原文貼進 Prompt。

執行 Day 19 Demo

專案加入:

demo-app/
├── rule-engine-demo/
│   ├── rules.json
│   └── scenario.js
└── recon-demo/
    └── architecture.json

先執行:

cd /media/mickey/777/ithome/demo-app
npm run rules:demo

這個指令會先重新產生 Day 18 的 architecture.json,再載入規則:

{
  "scripts": {
    "rules:demo": "npm run recon:demo >/dev/null && node rule-engine-demo/scenario.js"
  }
}

執行結果如下:

RULE CATALOG
SEC-AUTHZ-001 v1.0.0 domain=security applies_when=browser_direct_firestore
PRIV-MIN-001 v1.0.0 domain=privacy applies_when=stores_user_records
REL-TIMEOUT-001 v1.0.0 domain=reliability applies_when=calls_external_model_api
SEC-SECRET-001 v1.0.0 domain=security applies_when=client_has_api_key_field
SRE-HEALTH-001 v1.0.0 domain=reliability applies_when=long_running_server

EVALUATION
SEC-AUTHZ-001 CANDIDATE
  firestore.rules allows every authenticated identity to read and write projects.
  next: Run the two-account authorization scenario to confirm cross-account impact.
PRIV-MIN-001 CANDIDATE
  The project document stores ownerEmail and the project list renders it.
  next: Confirm the feature requirement and identify which users can read project documents.
REL-TIMEOUT-001 REQUIRES_EVIDENCE
  The Gemini call site has no explicit deadline in application code.
  next: Check SDK defaults and define the end-to-end review deadline before confirming a reliability gap.
SEC-SECRET-001 PASS
  The value identifies a localhost-only Firebase Emulator project and is not a Gemini credential.
SRE-HEALTH-001 NOT_APPLICABLE
  Applicability condition 'long_running_server' is false.

SUMMARY
pass: 1
candidate: 2
requires_evidence: 1
not_applicable: 1

規則引擎與 Gemini 如何分工?

今天的 Demo 使用 Deterministic JavaScript,沒有讓 Gemini 自由決定最後 Verdict。

這是刻意的設計。

比較安全的分工是:

Recon
建立架構、資料流與信任邊界

Rule Selector
根據 appliesWhen 選擇規則

Deterministic Tools
搜尋程式碼、讀取設定、執行測試

Gemini
解釋跨檔案語意、提出攻擊假設、整理缺少的證據

Validator
檢查引用、重現結果與 Verdict 上限

Gemini Function Calling 可以讓模型選擇外部工具,並產生符合 Function Schema 的參數。

未來可以提供:

read_file
search_code
run_authorization_test
inspect_dependency
request_project_evidence

但模型提出 Function Call,不代表工具可以直接獲得所有權限。

Host Application 仍要負責:

  • 驗證參數。
  • 限制可讀路徑。
  • 區分唯讀與會修改環境的工具。
  • 設定 Timeout 與輸出上限。
  • 保存執行證據。
  • 拒絕不符合目前 Rule 的工具呼叫。

規則定義「為什麼查」,工具提供「如何查」,Validator 決定「證據支持到哪一層結論」。

規則庫還需要哪些治理?

第一版 rules.json 仍然很小。

正式規則庫至少還需要:

  1. Schema Validation,拒絕缺少 ID、版本或適用條件的規則。
  2. Test Fixture,驗證安全與不安全範例的預期結果。
  3. Source Reference,記錄規則來自哪個版本的標準或內部政策。
  4. Deprecation,規則被取代時保留歷史對應。
  5. Severity Policy,把技術證據與業務環境分開評估。
  6. Exception Workflow,記錄風險接受、到期日與負責人。
  7. Evaluation Dataset,追蹤誤報、漏報與 requires_evidence 比例。

OWASP ASVS 提供可測試的 Web Application Security Requirements,也建議引用時帶上版本與 Requirement Identifier。

這類標準適合作為規則來源,卻不應不經轉換就成為 Finding。

一項 Requirement 還要結合應用架構、實作證據與可重現測試,才能變成 Agent 的判斷。

今天的結論

把知識交給 Agent,不是把更多文件塞進 Context Window。

一條可執行規則至少要回答:

  1. Rule ID 與版本是什麼?
  2. 哪種架構才適用?
  3. 判斷需要哪些證據?
  4. 使用哪個 Evaluator 或工具?
  5. 失敗時最高能輸出哪種 Verdict?
  6. 證據不足時下一步要查什麼?

今天的 Rule Engine 根據 Recon 結果選擇五條規則,最後產生:

1 Pass
2 Candidates
1 Requires Evidence
1 Not Applicable

這份結果比「發現四個問題」更有用。

它同時說明哪些控制已通過、哪些需要驗證、哪些缺少環境證據,以及哪些規則根本不適用。

明天,我們會建立 Security Hunter,讓 Gemini 根據適用規則與架構資料提出攻擊假設,再交給 Validator 篩掉無法重現的結論。

參考資料


上一篇
Day 18|從 Recon 開始:讓 Agent 看懂系統架構與信任邊界
下一篇
Day 20|讓 Gemini 穩定回答:實作 Structured Output 與驗證規則
系列文
從 Vibe Coding 到 Production:用 Google AI 打造上線守門員23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言